﻿Public Class AVPLPlaylist
  Implements IEnumerable(Of MobilePrettyGui.iPrettyListItem)

  ' Internal APPL version
  Public Const APPL_VERSION As Integer = 1

  ' These variables are for refreshing the contents of this list
  Private _lastFileQueryWhere As String = ""
  Private _lastFileQueryWhereParameters As New Dictionary(Of String, String)
  Private _lastFileQueryOrder As String = ""
  Private _lastFilePath As String = ""
  Private _lastFileIsQuery As Boolean = False
  Private _refreshEnabled As Boolean = False

  ' The actual playlist entries
  Private _entries As New List(Of AVPLPlaylistEntry)
  Private _shuffle As New List(Of Integer)

  Public ReadOnly Property Count() As Integer
    Get
      Return Me._entries.Count
    End Get
  End Property

  Private ReadOnly Property IsShuffleListValid() As Boolean
    Get
      If Me._entries.Count <> Me._shuffle.Count Then
        Return False
      Else
        For Each avple As AVPLPlaylistEntry In Me._entries
          Dim found As Boolean = False
          For Each i As Integer In Me._shuffle
            If i = avple.GetHashCode Then
              found = True
              Exit For
            End If
          Next
          If Not found Then
            Return False
          End If
        Next
      End If
      Return True
    End Get
  End Property

  Public Sub ReShuffle(ByVal startHash As Integer?) ' Shuffle with the current hashcode as the start of the list
    Dim tempEntries As New List(Of Integer)

    For Each avple As AVPLPlaylistEntry In Me._entries
      tempEntries.Add(avple.GetHashCode)
    Next

    Me._shuffle.Clear()

    If startHash IsNot Nothing Then
      For i As Integer = 0 To tempEntries.Count - 1
        If i = startHash Then
          Me._shuffle.Add(tempEntries(i))
          tempEntries.RemoveAt(i)
          Exit For
        End If
      Next
    End If

    Dim r As New Random()

    While tempEntries.Count > 0
      Dim idx As Integer = r.Next(0, tempEntries.Count - 1)
      Me._shuffle.Add(tempEntries(idx))
      tempEntries.RemoveAt(idx)
    End While
  End Sub

  Public Sub ReShuffle() ' Shuffle completely randomly
    Me.ReShuffle(Nothing)
  End Sub

  Public ReadOnly Property IsItemLastInShuffleList(ByVal hashcode As Integer?) As Boolean
    Get
      If hashcode Is Nothing Then
        Return False
      End If

      If Not Me.IsShuffleListValid Then
        Me.ReShuffle(hashcode)
      End If

      If Me._shuffle.Count > 1 Then
        If Me._shuffle.Last <> hashcode Then
          Return False
        End If
      End If

      Return True
    End Get
  End Property

  Public ReadOnly Property GetPreviousItemShuffled(ByVal avple As AVPLPlaylistEntry) As AVPLPlaylistEntry
    Get
      If avple IsNot Nothing Then
        Return Me.GetPreviousItemShuffled(avple.GetHashCode)
      End If
      Return Nothing
    End Get
  End Property

  Public ReadOnly Property GetPreviousItemShuffled(ByVal hashCode As Integer?) As AVPLPlaylistEntry
    Get
      If Me._entries.Count > 0 AndAlso hashCode IsNot Nothing Then
        If Not Me.IsShuffleListValid Then
          Me.ReShuffle(hashCode)
        End If

        If Me._shuffle.Count <= 0 Then
          Return Nothing
        End If

        ' Find the current hash code
        Dim prevFound As Boolean = False
        Dim prevHash As Integer = Me._shuffle.Last
        For Each i As Integer In Me._shuffle
          If i = hashCode Then
            prevFound = True
            Exit For
          End If
          prevHash = i
        Next

        If Not prevFound Then
          prevHash = Me._shuffle(0)
        End If

        For Each avple As AVPLPlaylistEntry In Me._entries
          If avple.GetHashCode = prevHash Then
            Return avple
          End If
        Next
      End If

      Return Nothing
    End Get
  End Property

  Public ReadOnly Property GetNextItemShuffled(ByVal avple As AVPLPlaylistEntry) As AVPLPlaylistEntry
    Get
      If avple IsNot Nothing Then
        Return Me.GetNextItemShuffled(avple.GetHashCode)
      End If
      Return Nothing
    End Get
  End Property

  Public ReadOnly Property GetNextItemShuffled(ByVal hashCode As Integer?) As AVPLPlaylistEntry
    Get
      If Me._entries.Count > 0 AndAlso hashCode IsNot Nothing Then
        If Not Me.IsShuffleListValid Then
          Me.ReShuffle(hashCode)
        End If

        If Me._shuffle.Count <= 0 Then
          Return Nothing
        End If

        ' Find the current hash code
        Dim curFound As Boolean = False
        Dim nextFound As Boolean = False
        Dim nextHash As Integer = Me._shuffle(0)
        For Each i As Integer In Me._shuffle
          If curFound Then
            nextFound = True
            nextHash = i
            Exit For
          End If
          If i = hashCode Then
            curFound = True
          End If
        Next

        If Not curFound OrElse Not nextFound Then
          nextHash = Me._shuffle(0)
        End If

        For Each avple As AVPLPlaylistEntry In Me._entries
          If avple.GetHashCode = nextHash Then
            Return avple
          End If
        Next
      End If

      Return Nothing
    End Get
  End Property

  Public Class AVPLPlaylistEnumerator
    Implements IEnumerator(Of MobilePrettyGui.iPrettyListItem)
    Private _entries As List(Of AVPLPlaylistEntry)
    Private _count As Integer = -1

    Public Sub New(ByRef entries As List(Of AVPLPlaylistEntry))
      Me._entries = entries
    End Sub

    Public ReadOnly Property Current() As MobilePrettyGui.iPrettyListItem Implements System.Collections.Generic.IEnumerator(Of MobilePrettyGui.iPrettyListItem).Current
      Get
        If Me._entries IsNot Nothing AndAlso Me._count >= 0 AndAlso Me._count < Me._entries.Count Then
          Return Me._entries(Me._count)
        End If

        Return Nothing
      End Get
    End Property

    Public ReadOnly Property Current1() As Object Implements System.Collections.IEnumerator.Current
      Get
        Return Me.Current()
      End Get
    End Property

    Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
      If Me._entries IsNot Nothing AndAlso Me._count < Me._entries.Count - 1 Then
        Me._count += 1
        Return True
      End If
      Return False
    End Function

    Public Sub Reset() Implements System.Collections.IEnumerator.Reset
      Me._count = -1
    End Sub

    Private disposedValue As Boolean = False    ' To detect redundant calls

    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
      If Not Me.disposedValue Then
        If disposing Then
          ' Nothing needs disposing (managed)
        End If
      End If
      Me.disposedValue = True
    End Sub

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
      ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
      Dispose(True)
      GC.SuppressFinalize(Me)
    End Sub
  End Class

  Public Class AVPLPlaylistException
    Inherits Exception
    Public Sub New(Optional ByVal message As String = "", Optional ByVal innerException As Exception = Nothing)
      MyBase.New(message, innerException)
    End Sub
  End Class

  Public Sub LoadFromFile(ByVal filename As String, Optional ByVal doNotLoadMissingFiles As Boolean = False)
    Try
      Dim inif As New AvianWaves.Ini.File
      inif.LoadFile(filename)

      Dim genSec As Ini.Section = inif.Section("General")
      If genSec Is Nothing Then ' Start "General" section processing
        Throw New AVPLPlaylistException("Malformatted AVPL: No 'General' section")
      Else
        Dim ver As Integer = genSec.IntegerValueNoNull("Version")
        If ver < 1 Then
          Throw New AVPLPlaylistException("Malformatted AVPL: Invalid version")
        ElseIf ver > APPL_VERSION Then
          Throw New AVPLPlaylistException("Cannot parse AVPL: Version " & ver & " is newer than what this version of Avian Play can support (" & APPL_VERSION & ")")
        End If

        Me._refreshEnabled = genSec.BooleanValueNoNull("ListRefreshEnabled")
        Me._lastFilePath = genSec.StringValueNoNull("RefreshPath")

        If Me._lastFilePath <> String.Empty Then
          Me._lastFileIsQuery = True
        Else
          Me._lastFileIsQuery = False
          Me._lastFileQueryWhere = genSec.StringValueNoNull("RefreshQueryWhere")
          Me._lastFileQueryOrder = genSec.StringValueNoNull("RefreshQueryOrder")

          ' Fetch the "where" parameters for the refresh query
          Dim found As Boolean = False
          Dim i As Integer = 1
          Me._lastFileQueryWhereParameters.Clear()
          Do
            Dim pKey As String = "RefreshQueryWhereParam" & i.ToString
            If genSec.ContainsKey(pKey) Then
              found = True
              Dim pVal As String = genSec.StringValueNoNull(pKey)
              Dim spl As Integer = pVal.IndexOf("=")
              If spl > 0 AndAlso spl < pVal.Length - 1 Then
                Dim key As String = pVal.Substring(0, spl - 1).Trim
                Dim val As String = pVal.Substring(spl + 1).Trim
                Me._lastFileQueryWhereParameters(key) = val
              ElseIf spl = pVal.Length - 1 Then
                Dim key As String = pVal.Substring(0, spl - 1).Trim
                Me._lastFileQueryWhereParameters(key) = ""
              End If
            Else
              found = False
            End If
            i += 1
          Loop While found
        End If
      End If ' End "General" section processing

      ' Begin processing all the playlist entries
      Dim entryCount As Integer = 1
      Dim entrySection As Ini.Section = inif.Section("Entry" & entryCount.ToString)
      While entrySection IsNot Nothing
        ' What type of entry?
        Dim eType As Integer? = entrySection.IntegerValue("Type")
        If eType IsNot Nothing Then
          Select Case eType
            Case AVPLPlaylistEntry.EntryType.File     ' Process the FILE type of entry
              Dim aple As New AVPLPlaylistEntry
              aple.Type = AVPLPlaylistEntry.EntryType.File

              Dim fp As String = entrySection.StringValue("FilePath") ' required!
              If fp Is Nothing Then
                Throw New AVPLPlaylistException("Cannot parse AVPL: Entry " & entryCount.ToString & ": 'FilePath' is a required parameter in 'File' type entries.")
              Else
                aple.FilePath = fp
              End If

              aple.Artist = entrySection.StringValueNoNull("Artist")
              aple.AlbumArtist = entrySection.StringValueNoNull("AlbumArtist")
              aple.Title = entrySection.StringValueNoNull("Title")
              aple.Album = entrySection.StringValueNoNull("Album")
              aple.Genre = entrySection.StringValueNoNull("Genre")

              If Not doNotLoadMissingFiles OrElse IO.File.Exists(fp) Then
                Me._entries.Add(aple)
              End If
            Case AVPLPlaylistEntry.EntryType.Stream   ' Process the STREAM type of entry
              Dim aple As New AVPLPlaylistEntry
              aple.Type = AVPLPlaylistEntry.EntryType.Stream

              If entrySection.StringValue("StreamTitle") Is Nothing Then
                aple.StreamTitle = entrySection.StringValueNoNull("Title") ' This is being tolerant of incorrectly formatted AVPL
              Else
                aple.StreamTitle = entrySection.StringValueNoNull("StreamTitle")
              End If
              aple.StreamSubtitle = entrySection.StringValueNoNull("StreamSubtitle")
              aple.LastStreamRefresh = New Date(entrySection.LongValueNoNull("StreamPlaylistLastRefresh")) ' Ticks are a LONG, not an integer!
              aple.StreamPlaylistUrlString = entrySection.StringValueNoNull("StreamPlaylistURL")
              aple.StreamUsePlaylistUrlOnce = entrySection.BooleanValueNoNull("StreamUsePlaylistURLOnce")

              Dim i As Integer = 1
              Dim urlStr As String = "StreamURL" & i
              While entrySection.ContainsKey(urlStr)
                Dim newUrl As String = entrySection.StringValueNoNull(urlStr)
                If newUrl <> String.Empty Then
                  Try
                    aple.StreamURLs.Add(New Uri(newUrl))
                  Catch
                    ' URI is invalid, exclude this entry
                    Exit Select
                  End Try
                End If
                i += 1
                urlStr = "StreamURL" & i
              End While

              Me._entries.Add(aple)
            Case AVPLPlaylistEntry.EntryType.Meta
              Throw New AVPLPlaylistException("Cannot parse AVPL: Entry " & entryCount.ToString & ": 'meta' types are not supported in this version.")
            Case Else
              Throw New AVPLPlaylistException("Cannot parse AVPL: Entry " & entryCount.ToString & " has an invalid 'type' field.")
          End Select
        Else
          Throw New AVPLPlaylistException("Cannot parse AVPL: Entry " & entryCount.ToString & " has a missing 'type' field.")
        End If

        ' Increment the counter and load the next section
        entryCount += 1
        entrySection = inif.Section("Entry" & entryCount.ToString)
      End While
    Catch ex As AVPLPlaylistException
      Throw
    Catch ex As Exception
      Throw New AVPLPlaylistException("Unable to save AVPL [General].", ex)
    End Try
  End Sub

  Public Sub SaveToFile(ByVal filename As String)
    Try
      Dim ini As New AvianWaves.Ini.File
      ini.AddSection("General")
      With ini.Section("General")
        .Add("Version", APPL_VERSION.ToString)
        .Add("ListRefreshEnabled", Me._refreshEnabled)
        If Me._refreshEnabled Then
          If Me._lastFileIsQuery Then
            .Add("RefreshQueryWhere", Me._lastFileQueryWhere)
            For i As Integer = 0 To Me._lastFileQueryWhereParameters.Count - 1
              .Add("RefreshQueryWhereParam" & (i + 1).ToString, Me._lastFileQueryWhereParameters.Keys(i) & " = " & Me._lastFileQueryWhereParameters.Values(i))
            Next
            .Add("RefreshQueryOrder", Me._lastFileQueryOrder)
          Else
            .Add("RefreshPath", Me._lastFilePath)
          End If
        End If
      End With

      For i As Integer = 0 To Me._entries.Count - 1
        Dim secName As String = "Entry" & (i + 1).ToString
        ini.AddSection(secName)
        With ini.Section(secName)
          ' General parameters
          .Add("Type", CInt(Me._entries(i).Type))

          ' Type specific parameters
          Select Case Me._entries(i).Type
            Case AVPLPlaylistEntry.EntryType.File
              .Add("FilePath", Me._entries(i).FilePath)
              If Me._entries(i).Artist.Trim.Length > 0 Then .Add("Artist", Me._entries(i).Artist)
              If Me._entries(i).AlbumArtist.Trim.Length > 0 Then .Add("AlbumArtist", Me._entries(i).AlbumArtist)
              If Me._entries(i).Title.Trim.Length > 0 Then .Add("Title", Me._entries(i).Title)
              If Me._entries(i).Album.Trim.Length > 0 Then .Add("Album", Me._entries(i).Album)
              If Me._entries(i).Genre.Trim.Length > 0 Then .Add("Genre", Me._entries(i).Genre)

            Case AVPLPlaylistEntry.EntryType.Stream
              If Me._entries(i).StreamTitle.Trim.Length > 0 Then .Add("StreamTitle", Me._entries(i).StreamTitle)
              If Me._entries(i).StreamSubtitle.Trim.Length > 0 Then .Add("StreamSubtitle", Me._entries(i).StreamSubtitle)
              .Add("StreamPlaylistLastRefresh", Me._entries(i).LastStreamRefresh.Ticks) ' It's important to remember this is a LONG, not an integer
              If Me._entries(i).StreamPlaylistUrlString.Trim.Length > 0 Then .Add("StreamPlaylistURL", Me._entries(i).StreamPlaylistUrlString)
              If Me._entries(i).StreamUsePlaylistUrlOnce Then .Add("StreamUsePlaylistUrlOnce", "1")
              For j As Integer = 0 To Me._entries(i).StreamURLs.Count - 1
                .Add("StreamURL" & (j + 1).ToString, Me._entries(i).StreamURLs(j).ToString)
              Next

            Case AVPLPlaylistEntry.EntryType.Meta
              ' Not yet implemented
              Throw New AVPLPlaylistException("AVPL: META Query is not supported in this version.")
          End Select
        End With
      Next

      ' Now commit the file
      ini.Save(filename)
    Catch ex As Threading.ThreadAbortException
      Throw
    Catch ex As AVPLPlaylistException
      Throw
    Catch ex As Exception
      Throw New AVPLPlaylistException("Unable to save AVPL playlist.", ex)
    End Try
  End Sub

  Public Property LastFileQueryWhereString() As String
    Get
      Return Me._lastFileQueryWhere
    End Get
    Set(ByVal value As String)
      Me._lastFileQueryWhere = value
    End Set
  End Property

  Public WriteOnly Property LastFileQueryWhereParameters() As List(Of Data.SqlServerCe.SqlCeParameter)
    Set(ByVal value As List(Of Data.SqlServerCe.SqlCeParameter))
      Me._lastFileQueryWhereParameters.Clear()
      If value IsNot Nothing Then
        For Each p As Data.SqlServerCe.SqlCeParameter In value
          Me._lastFileQueryWhereParameters.Add(p.ParameterName, p.Value.ToString)
        Next
      End If
    End Set
  End Property

  Public Property LastFileQueryOrder() As String
    Get
      Return Me._lastFileQueryOrder
    End Get
    Set(ByVal value As String)
      Me._lastFileQueryOrder = value
    End Set
  End Property

  Public Property LastFilePath() As String
    Get
      Return Me._lastFilePath
    End Get
    Set(ByVal value As String)
      Me._lastFilePath = value
    End Set
  End Property

  Public Property LastFileIsQuery() As Boolean
    Get
      Return Me._lastFileIsQuery
    End Get
    Set(ByVal value As Boolean)
      Me._refreshEnabled = True
      Me._lastFileIsQuery = value
    End Set
  End Property

  Public Sub SetRefreshDisabled()
    Me._refreshEnabled = False
  End Sub

  Public Property Entries() As List(Of AVPLPlaylistEntry)
    Get
      Return Me._entries
    End Get
    Set(ByVal value As List(Of AVPLPlaylistEntry))
      Me._entries = value
    End Set
  End Property

  Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of MobilePrettyGui.iPrettyListItem) Implements System.Collections.Generic.IEnumerable(Of MobilePrettyGui.iPrettyListItem).GetEnumerator
    Dim en As New AVPLPlaylistEnumerator(Me._entries)
    Return en
  End Function

  Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
    Return CType(Me._entries, IEnumerable).GetEnumerator
  End Function





  Private _mainThreadForm As Windows.Forms.Form = Nothing
  Private _refreshThread As Threading.Thread = Nothing
  Private _daysOld As Integer = 0

  Public Sub AbortRefreshStreamURLs()
    If Me._refreshThread IsNot Nothing Then
      Me._refreshThread.Abort()
    End If
  End Sub

  Public Sub RefreshStreamURLs(ByVal mainThreadForm As Windows.Forms.Form, ByVal daysOld As Integer)
    Me.AbortRefreshStreamURLs()

    If daysOld >= 0 Then
      Dim shouldRefresh As Boolean = False
      For Each ape In Me._entries
        If ape.Type = AVPLPlaylistEntry.EntryType.Stream Then
          shouldRefresh = True
          Exit For
        End If
      Next

      If shouldRefresh Then
        Me._mainThreadForm = mainThreadForm
        Me._daysOld = daysOld
        Me._refreshThread = New Threading.Thread(AddressOf RefreshStreamURLsThread)
        Me._refreshThread.Priority = Threading.ThreadPriority.BelowNormal
        Me._refreshThread.Start()
      End If
    End If
  End Sub

  Private Sub RefreshStreamURLsThread()
    Try
      Dim avpl As New AVPLPlaylist

      ' Build the list of playlist stream URLs to update
      For Each ape As AVPLPlaylistEntry In Me._entries
        If ape.Type = AVPLPlaylistEntry.EntryType.Stream AndAlso ape.StreamPlaylistUrl IsNot Nothing Then
          Dim aper As New AVPLPlaylistEntry
          aper.Type = AVPLPlaylistEntry.EntryType.Stream
          aper.StreamPlaylistUrlString = ape.StreamPlaylistUrlString
          aper.StreamUsePlaylistUrlOnce = ape.StreamUsePlaylistUrlOnce
          avpl.Entries.Add(aper)
        End If
      Next

      If avpl.Count > 0 Then
        ' Update all the URLs
        For Each ape As AVPLPlaylistEntry In avpl
          If Date.Now.Subtract(ape.LastStreamRefresh).Days >= Me._daysOld Then
            Try
              ' Store the playlist URL in case it gets set to nothing due to it being a 'use once' URL
              Dim plurl As New Uri(ape.StreamPlaylistUrl, "")

              ' Update the list of URLs
              ape.RefreshStreamURLsFromPlaylistURL()

              ' Now, it's possible the URL was a 'use once' URL and it may have removed the URL as a result
              If ape.StreamPlaylistUrl Is Nothing Then
                ' Flag this as a 'use once' URL and reset the playlist URL for comparison on the UpdateStreamURLs method
                ape.Artist = "USEONCE"
                ape.StreamPlaylistUrl = plurl
              End If
            Catch
              ' We're on a thread doing this automatically, so just eat the exception - it's getting written to the log anyway
            End Try
          Else
            ' Set to nothing, because we do not update and there is no need further down the line to process the list of URLs if there is no change
            ape.StreamPlaylistUrl = Nothing
          End If
        Next

        ' Now update back on the main thread
        Me.UpdateStreamURLs(avpl)
      End If
    Catch ex As Threading.ThreadAbortException
      ' Safe to ignore!
    Catch ex As Exception
      ' Catch all other errors
      ErrorLog.WriteToErrorLog("RefreshStreamURLsThread() :: " & ex.ToString)
    End Try
  End Sub

  Public Sub SortByText()
    For Each ape As AVPLPlaylistEntry In Me._entries
      ape.SortBy = AVPLPlaylistEntry.SortMode.Text
    Next
    Me._entries.Sort()
  End Sub

  Public Sub SortBySubtext()
    For Each ape As AVPLPlaylistEntry In Me._entries
      ape.SortBy = AVPLPlaylistEntry.SortMode.Subtext
    Next
    Me._entries.Sort()
  End Sub

  Public Sub SortByType()
    For Each ape As AVPLPlaylistEntry In Me._entries
      ape.SortBy = AVPLPlaylistEntry.SortMode.Type
    Next
    Me._entries.Sort()
  End Sub

  Private Delegate Sub UpdateStreamURLsDelegate(ByVal newEntries As AVPLPlaylist)
  Private Sub UpdateStreamURLs(ByVal newEntries As AVPLPlaylist)
    If _mainThreadForm IsNot Nothing Then
      If _mainThreadForm.InvokeRequired Then
        Dim del As New UpdateStreamURLsDelegate(AddressOf UpdateStreamURLs)
        _mainThreadForm.Invoke(del, New Object() {newEntries})
      Else
        For Each oldApe As AVPLPlaylistEntry In Me._entries
          If oldApe.Type = AVPLPlaylistEntry.EntryType.Stream AndAlso oldApe.StreamPlaylistUrlString.Length > 0 Then
            For Each newApe As AVPLPlaylistEntry In newEntries
              If String.Compare(newApe.StreamPlaylistUrlString, oldApe.StreamPlaylistUrlString, True) = 0 Then
                ' Only update the URLs if we have any
                If newApe.StreamURLs.Count > 0 Then
                  oldApe.StreamURLs = newApe.StreamURLs
                End If

                ' Always update the refresh time (so we don't constantly refresh the stream)
                oldApe.LastStreamRefresh = newApe.LastStreamRefresh

                ' Update the 'use once' parameter and the URL source (the 'artist' property is set by the RefreshStreamURLsThread because that method does not use any tag data from files as it is designed only to update URLs in the background)
                If newApe.Artist = "USEONCE" Then
                  oldApe.StreamUsePlaylistUrlOnce = False ' Clear the value, we've used it once
                  oldApe.StreamPlaylistUrl = Nothing ' Set the playlist to nothing because we've exhausted the 'use once' URL
                End If
              End If
            Next
          End If
        Next
      End If
    End If
  End Sub

  Public Shared Function FromStandardPlaylist(ByVal spl As StandardPlaylist) As AVPLPlaylist
    If spl IsNot Nothing Then
      Dim avpl As New AVPLPlaylist

      For Each e As StandardPlaylistEntry In spl.Entries
        Dim avple As New AVPLPlaylistEntry
        Dim valid As Boolean = True

        ' Try to build a URI out of the location and extract path; on failure assume local file path
        Try
          Dim u As New Uri(e.Location)
          If u.Scheme.Trim.ToUpper = "FILE" Then
            avple.Type = AVPLPlaylistEntry.EntryType.File
            avple.FilePath = u.LocalPath
          Else
            avple.Type = AVPLPlaylistEntry.EntryType.Stream
            avple.StreamURLs.Add(u)
          End If
        Catch
          avple.Type = AVPLPlaylistEntry.EntryType.File
          avple.FilePath = e.Location
        End Try

        If avple.Type = AVPLPlaylistEntry.EntryType.File Then
          avple.Title = e.Title
          If avple.FilePath.Length > 0 Then
            If avple.FilePath(0) <> "\"c Then ' Must add the preceding \ as relative paths are NOT supported
              avple.FilePath = "\" & avple.FilePath
            End If
          Else
            valid = False
          End If
        ElseIf avple.Type = AVPLPlaylistEntry.EntryType.Stream Then
          avple.StreamTitle = e.Title
          If avple.StreamURLs.Count <= 0 Then
            valid = False
          End If
        Else
          valid = False
        End If

        If valid Then
          avpl.Entries.Add(avple)
        End If
      Next

      Return avpl
    Else
      Return Nothing
    End If
  End Function

End Class
